package com.dbh.company.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.Base64Utils;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.security.*;

/**
 * Created by lvxiaojun on 2017/2/20.
 * 加密工具类
 */
public class EncryptUtil {

    public static final Logger LOGGER = LoggerFactory.getLogger(EncryptUtil.class);

    public static final String ALGORITHM_AES = "AES";
    public static final int SECRET_KEY_LENGTH = 128;
    public static final String DEFAULT_CHARSET = "UTF-8";


    /**
     * 偏移变量，固定占8位字节
     */
    private final static String IV_PARAMETER = "12345678";
    /**
     * 密钥算法
     */
    private static final String ALGORITHM = "DES";
    /**
     * 加密/解密算法-工作模式-填充模式
     */
    private static final String CIPHER_ALGORITHM = "DES/CBC/PKCS5Padding";
    /**
     * 默认编码
     */
    private static final String CHARSET = "utf-8";

    /**
     * AES加密
     * @param content 加密内容
     * @param secretKey 私钥
     * @return 密文
     */
    public static String AESEncode(String content, String secretKey) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_AES);
            keyGenerator.init(SECRET_KEY_LENGTH, new SecureRandom(secretKey.getBytes()));
            SecretKey sk = keyGenerator.generateKey();
            byte[] enCodeFormat = sk.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, ALGORITHM_AES);
            Cipher cipher = Cipher.getInstance(ALGORITHM_AES);// 创建密码器
            byte[] byteContent = content.getBytes(DEFAULT_CHARSET);
            cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化
            byte[] result = cipher.doFinal(byteContent);
            //return new String(Base64.getEncoder().encode(result)); // 加密
            return Base64.encodeToString(result);
        } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | BadPaddingException | UnsupportedEncodingException | IllegalBlockSizeException e) {
            LOGGER.error("Encrypt Error.", e);
        }
        return "";
    }

    /**
     * AES解密
     * @param content 加密内容
     * @param secretKey 私钥
     * @return 密文
     */
    public static String AESDecode(String content, String secretKey) {
        try {
            KeyGenerator keyGenerator = KeyGenerator.getInstance(ALGORITHM_AES);
            keyGenerator.init(SECRET_KEY_LENGTH, new SecureRandom(secretKey.getBytes()));
            SecretKey sk = keyGenerator.generateKey();
            byte[] enCodeFormat = sk.getEncoded();
            SecretKeySpec key = new SecretKeySpec(enCodeFormat, ALGORITHM_AES);
            Cipher cipher = Cipher.getInstance(ALGORITHM_AES);// 创建密码器
            cipher.init(Cipher.DECRYPT_MODE, key);// 初始化
            byte[] result = cipher.doFinal(content.getBytes());
            return new String(result); // 加密
        } catch (NoSuchAlgorithmException | InvalidKeyException | NoSuchPaddingException | BadPaddingException | IllegalBlockSizeException e) {
            LOGGER.error("Decrypt Error.", e);
        }
        return "";
    }

    public static String SHA256Encode(String content, String secretKey) {
        try {
            String contentToEncrypt = content + secretKey;
            MessageDigest md = MessageDigest.getInstance("SHA-256");
            md.update(content.getBytes());
            return bytes2Hex(md.digest());
        } catch (NoSuchAlgorithmException e) {
        }
        return "";
    }

    public static String MD5(String s) {
        char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

        try {
            byte[] btInput = s.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public static String bytes2Hex(byte[] bts) {
        String des = "";
        String tmp;
        for (byte bt : bts) {
            tmp = (Integer.toHexString(bt & 0xFF));
            if (tmp.length() == 1) {
                des += "0";
            }
            des += tmp;
        }
        return des;
    }



    /**
     * 生成key
     *
     * @param password
     * @return
     * @throws Exception
     */
    private static Key generateKey(String password) throws Exception {
        DESKeySpec dks = new DESKeySpec(password.getBytes(CHARSET));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(ALGORITHM);
        return keyFactory.generateSecret(dks);
    }


    /**
     * DES加密字符串
     *
     * @param password 加密密码，长度不能够小于8位
     * @param data 待加密字符串
     * @return 加密后内容
     */
    public static String DESEncrypt(String password, String data) {
        if (password== null || password.length() < 8) {
            throw new RuntimeException("DES-加密失败，key不能小于8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(password);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            byte[] bytes = cipher.doFinal(data.getBytes(CHARSET));

            //JDK1.8及以上可直接使用Base64，JDK1.7及以下可以使用BASE64Encoder
            //Android平台可以使用android.util.Base64
            return new String(Base64.encodeToString(bytes));

        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }


    /**
     * DES加密字符串
     *
     * @param password 加密密码，长度不能够小于8位
     * @param data 待加密字符串
     * @return 加密后内容
     */
    public static String DESEncrypt2(String password, String data) {
        if (password== null || password.length() < 8) {
            throw new RuntimeException("DES-加密失败，key不能小于8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(password);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.ENCRYPT_MODE, secretKey, iv);
            byte[] bytes = cipher.doFinal(data.getBytes(CHARSET));

            //JDK1.8及以上可直接使用Base64，JDK1.7及以下可以使用BASE64Encoder
            //Android平台可以使用android.util.Base64
            return new String(Base64Utils.encodeToString(bytes)).replace(" ", "+");

        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }


    /**
     * DES解密字符串
     *
     * @param password 解密密码，长度不能够小于8位
     * @param data 待解密字符串
     * @return 解密后内容
     */
    public static String DESDecrypt(String password, String data) {
        if (password == null || password.length() < 8) {
            throw new RuntimeException("DES-加密失败，key不能小于8位");
        }
        if (data == null)
            return null;
        try {
            Key secretKey = generateKey(password);
            Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
            IvParameterSpec iv = new IvParameterSpec(IV_PARAMETER.getBytes(CHARSET));
            cipher.init(Cipher.DECRYPT_MODE, secretKey, iv);
            return new String(cipher.doFinal(Base64.decode(data.getBytes(CHARSET))), CHARSET);
        } catch (Exception e) {
            e.printStackTrace();
            return data;
        }
    }

    public static void main(String[] args) throws Exception {
//        String s = DESEncrypt2("abcqwertty", "instanceId=22172456&ak=wwkz9kgivwl42gw08uwzuo8n&application=ppyyhzz_contract");
//        System.out.println(s);
        String s2 = DESDecrypt("abcqwertty", "JiaFangLingXingZhiFuYiFangBuChangKuanJinE");
        System.out.println(s2);

    }
}
